package com.apobates.forum.orize.core.plug;

import com.apobates.forum.orize.OrizeResource;
import com.apobates.forum.orize.OrizeResources;
import com.apobates.forum.orize.core.OrizeResourceLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.util.Collection;
import java.util.Collections;

/**
 * XML文件中定义资源
 * XML文件结构示例:
 * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 * <resources stamp="20210805">
 *   <item>
 *     <path>/orders/list</path>
 *     <method>get</method>
 *     <action>VIEW</action>
 *     <roles>Member</roles>
 *     <spot>do</spot>
 *   </item>
 *   ...
 * </resources>
 * @author xiaofanku@live.cn
 * @since 20210822
 */
public class OrizeResourceXmlLoader implements OrizeResourceLoader {
    private final String xmlFilePath;
    private final static Logger logger = LoggerFactory.getLogger(OrizeResourceXmlLoader.class);
    public final static String ANNO_RES_DEF_FILENAME="annotation_resources.xml";
    static {
        logger.info("[OrizeResourceXmlLoader]set global system property");
        System.setProperty("javax.xml.bind.context.factory","org.eclipse.persistence.jaxb.JAXBContextFactory");
    }

    public OrizeResourceXmlLoader(String xmlFilePath) {
        this.xmlFilePath = xmlFilePath;
    }

    public Document load() {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new File(xmlFilePath));
            return doc;
        }catch (Exception e){
            if(logger.isDebugEnabled()){
                logger.debug(e.getMessage(), e);
            }
        }
        throw new IllegalStateException("解析XML资源定义失败");
    }


    public static void marshal(OrizeResources rss, String xmlFilePath) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(OrizeResources.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        //Marshal the employees list in file
        jaxbMarshaller.marshal(rss, new File(xmlFilePath));
    }

    private static Collection<OrizeResource> unmarshal(String xmlFilePath) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(OrizeResources.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

        StreamSource xml = new StreamSource(new File(xmlFilePath));
        OrizeResources rss = jaxbUnmarshaller.unmarshal(xml, OrizeResources.class).getValue();
        //
        try {
            return rss.getResources();
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }
}
